#ifndef __AE_H
#define __AE_H

#define AE_OK 0
#define AE_ERR -1

/* 事件的类型 */
#define AE_NONE 0
#define AE_READABLE 1
#define AE_WRITABLE 2

#define AE_FILE_EVENTS 1
#define AE_TIME_EVENTS 2
#define AE_ALL_EVENTS (AE_FILE_EVENTS | AE_TIME_EVENTS)
#define AE_DONT_WAIT 4

#define AE_NOMORE -1


/* 一些宏命令 */
#define AE_NOTUSED(V) ((void) V)

/* 定义事件循环 */
struct aeEventLoop;

/* 类型和数据结构 */

/* 事件对应的处理函数 */
typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);
/* 返回值是剩余事件, 处理时间事件 */
typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);
/* 时间到期处理函数 */
typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);
/* 休眠之前的处理函数 */
typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);

/* file event的结构 */
typedef struct aeFileEvent {
    int mask; /* AE_WRITABLE或者AE_READABLE事件 */
    aeFileProc *rfileProc; /* 读事件的处理函数 */
    aeFileProc *wfileProc; /* 写事件的处理函数 */
    void *clientData; /* 客户端的数据 */
} aeFileEvent;

/* time event的结构 */
typedef struct aeTimeEvent {
    long long id; /* time event的标识符 */
    long when_sec; /* 秒 */
    long when_ms; /* 毫秒 */
    aeTimeProc *timeProc; /* time event处理程序 */
    aeEventFinalizerProc *finalizerProc; /* 时间到期的处理函数 */
    void *clientData; /* 客户端数据 */
    struct aeTimeEvent *next; /* 下一个时间事件 */
} aeTimeEvent;


/* 已经准备好的事件 */
typedef struct aeFiredEvent {
    int fd; /* 文件描述符 */
    int mask; /* 事件的类型 */
} aeFiredEvent;

/* 事件循环的程序 */
typedef struct aeEventLoop {
    int maxfd; /* 当前注册最大的文件描述符id */
    int setsize; /* 可以跟踪的最多fd数目 */
    long long timeEventNextId; /* 下一个时间事件的id */
    time_t lastTime; /*? 用于检测系统的时钟倾斜 */
    aeFileEvent *events; /* 文件事件列表 */
    aeFiredEvent *fired; /* 已经完成的事件列表 */
    aeTimeEvent *timeEventHead; /* 时间事件头 */
    int stop; /* 是否停止 0-开启 1-停止 */
    void *apidata; /* polling api的数据 */
    aeBeforeSleepProc *beforesleep; /* 每次休眠之前的处理函数 */
} aeEventLoop;

/* 函数原型 */
aeEventLoop *aeCreateEventLoop(int setsize);
void aeDeleteEventLoop(aeEventLoop *eventLoop);
void aeStop(aeEventLoop *eventLoop);
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
        aeFileProc *proc, void *clientData);
void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask);
int aeGetFileEvents(aeEventLoop *eventLoop, int fd);
long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
        aeTimeProc *proc, void *clientData,
        aeEventFinalizerProc *finalizerProc);
int aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id);
int aeProcessEvents(aeEventLoop *eventLoop, int flags);
int aeWait(int fd, int mask, long long milliseconds);
void aeMain(aeEventLoop *eventLoop);
char *aeGetApiName(void);
void aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep);
int aeGetSetSize(aeEventLoop *eventLoop);
int aeResizeSetSize(aeEventLoop *eventLoop, int setsize);



#endif